using System;
using System.Collections.Generic;
using System.Threading;
using Ioc.Kernel;
using Ioc.Kernel.LifeStyles;
using TestClasses.Business;
using TestClasses.Daos;

namespace KernelProfilingApp
{
    public class AllProcessesBusiness
    {
        private static readonly object workerLocker = new object();
        private static int workerCount;

        #region ProcessThreadDependency

        public void ProcessThreadDependency(IIocContainer container)
        {
            ConfigureThreadDependency(container);

            for (int i = 0; i < 100; ++i)
            {
                lock (workerLocker)
                {
                    ++workerCount;
                }
                var thread = new Thread(ThreadProcessResolce);
                thread.Start(container);
            }

            lock (workerLocker)
            {
                while (workerCount > 0)
                    Monitor.Wait(workerLocker, 2000);
            }

            container.RemoveAllComponents();
        }

        private void ThreadProcessResolce(object container)
        {

            try
            {
                ProcessResolve(container as IocContainer);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                Console.ReadLine();
            }

            lock (workerLocker)
            {
                --workerCount;
                Monitor.Pulse(workerLocker);
            }
        }

        private void ConfigureThreadDependency(IIocContainer container)
        {
            container.AddComponent("Business1", typeof(Business1), typeof(IBusiness123), new List<Parameter>
                                                                                             {
                                                                                                 new Parameter {Name = "parameter1", Value = "parameter1"}
                                                                                             });
            container.AddComponent("Business2", typeof(Business2), typeof(IBusiness123));
            container.AddComponent("Business3", typeof(Business3), typeof(IBusiness123), new List<Parameter>
                                                                                             {
                                                                                                 //new Parameter {Name = "Business", Value = "${Business5}"},
                                                                                                 new Parameter {Name = "innerDao1", Value = "${Dao2}"},
                                                                                                 new Parameter {Name = "innerDao2", Value = "${Dao3}"}
                                                                                             });
            container.AddComponent("Business4", typeof(Business4), typeof(IBusiness45), new List<Parameter>
                                                                                             {
                                                                                                 new Parameter {Name = "dao", Value = "${Dao4}"}
                                                                                             });
            container.AddComponent("Business5", typeof(Business5), typeof(IBusiness45), LifeStyleType.PerThread, new List<Parameter>
                                                                                            {
                                                                                                new Parameter {Name = "parameter1", Value = "parameter1"},
                                                                                                new Parameter {Name = "parameter2", Value = "2"},
                                                                                                new Parameter {Name = "dao", Value = "${Dao5}"}
                                                                                            });
            container.AddComponent("Dao1", typeof(Dao1), typeof(IDao123), LifeStyleType.PerThread);
            container.AddComponent("Dao2", typeof(Dao2), typeof(IDao123), LifeStyleType.PerThread);
            container.AddComponent("Dao3", typeof(Dao3), typeof(IDao123), LifeStyleType.PerThread);
            container.AddComponent("Dao4", typeof(Dao4), typeof(IDao45), LifeStyleType.PerThread);
            container.AddComponent("Dao5", typeof(Dao5), typeof(IDao45), LifeStyleType.PerThread);
        }

        #endregion

        #region ProcessSingletonDependency

        public void ProcessSingletonDependency(IIocContainer container)
        {
            ConfigureSingletonDependency(container);

            for (int i = 0; i < 100; i++)
            {
                ProcessResolve(container);
            }

            container.RemoveAllComponents();
        }

        private void ConfigureSingletonDependency(IIocContainer container)
        {
            container.AddComponent("Business1", typeof(Business1), typeof(IBusiness123), new List<Parameter>
                                                                                             {
                                                                                                 new Parameter {Name = "parameter1", Value = "parameter1"}
                                                                                             });
            container.AddComponent("Business2", typeof(Business2), typeof(IBusiness123));
            container.AddComponent("Business3", typeof(Business3), typeof(IBusiness123), new List<Parameter>
                                                                                             {
                                                                                                 new Parameter {Name = "Business", Value = "${Business5}"},
                                                                                                 new Parameter {Name = "innerDao1", Value = "${Dao2}"},
                                                                                                 new Parameter {Name = "innerDao2", Value = "${Dao3}"}
                                                                                             });
            container.AddComponent("Business4", typeof(Business4), typeof(IBusiness45), new List<Parameter>
                                                                                             {
                                                                                                 new Parameter {Name = "dao", Value = "${Dao5}"}
                                                                                             });
            container.AddComponent("Business5", typeof(Business5), typeof(IBusiness45), LifeStyleType.Singleton, new List<Parameter>
                                                                                            {
                                                                                                new Parameter {Name = "parameter1", Value = "parameter1"},
                                                                                                new Parameter {Name = "parameter2", Value = "2"},
                                                                                                new Parameter {Name = "dao", Value = "${Dao5}"}
                                                                                            });
            container.AddComponent("Dao1", typeof(Dao1), typeof(IDao123), LifeStyleType.Singleton);
            container.AddComponent("Dao2", typeof(Dao2), typeof(IDao123), LifeStyleType.Singleton);
            container.AddComponent("Dao3", typeof(Dao3), typeof(IDao123), LifeStyleType.Singleton);
            container.AddComponent("Dao4", typeof(Dao4), typeof(IDao45), LifeStyleType.Singleton);
            container.AddComponent("Dao5", typeof(Dao5), typeof(IDao45), LifeStyleType.Singleton);
        }

        #endregion

        #region ProcessNamedTransientDependency

        public void ProcessNamedTransientDependency(IIocContainer container)
        {
            ConfigureNamedTransientDependency(container);

            for (int i = 0; i < 100; i++)
            {
                ProcessResolve(container);
            }

            container.RemoveAllComponents();
        }

        private void ConfigureNamedTransientDependency(IIocContainer container)
        {
            container.AddComponent("Business1", typeof(Business1), typeof(IBusiness123), new List<Parameter>
                                                                                             {
                                                                                                 new Parameter {Name = "parameter1", Value = "parameter1"}
                                                                                             });
            container.AddComponent("Business2", typeof(Business2), typeof(IBusiness123));
            container.AddComponent("Business3", typeof(Business3), typeof(IBusiness123), new List<Parameter>
                                                                                             {
                                                                                                 new Parameter {Name = "Business", Value = "${Business5}"},
                                                                                                 new Parameter {Name = "innerDao1", Value = "${Dao1}"},
                                                                                                 new Parameter {Name = "innerDao2", Value = "${Dao2}"}
                                                                                             });
            container.AddComponent("Business4", typeof(Business4), typeof(IBusiness45), new List<Parameter>
                                                                                             {
                                                                                                 new Parameter {Name = "dao", Value = "${Dao4}"}
                                                                                             });
            container.AddComponent("Business5", typeof(Business5), typeof(IBusiness45), new List<Parameter>
                                                                                            {
                                                                                                new Parameter {Name = "parameter1", Value = "parameter1"},
                                                                                                new Parameter {Name = "parameter2", Value = "2"},
                                                                                                new Parameter {Name = "dao", Value = "${Dao5}"}
                                                                                            });
            container.AddComponent("Dao1", typeof(Dao1), typeof(IDao123));
            container.AddComponent("Dao2", typeof(Dao2), typeof(IDao123));
            container.AddComponent("Dao3", typeof(Dao3), typeof(IDao123));
            container.AddComponent("Dao4", typeof(Dao4), typeof(IDao45));
            container.AddComponent("Dao5", typeof(Dao5), typeof(IDao45));
        }

        #endregion

        #region ProcessSimpleTransientDependency

        public void ProcessSimpleTransientDependency(IIocContainer container)
        {
            ConfigureSimpleTransientDependency(container);

            for (int i = 0; i < 100; i++)
            {
                ProcessResolve(container);
            }

            container.RemoveAllComponents();
        }

        private void ConfigureSimpleTransientDependency(IIocContainer container)
        {
            container.AddComponent("Business1", typeof(Business1), typeof(IBusiness123), new List<Parameter>
                                                                                                 {
                                                                                                     new Parameter {Name = "parameter1", Value = "parameter1"},
                                                                                                 });
            container.AddComponent("Business2", typeof(Business2), typeof(IBusiness123));
            container.AddComponent("Business3", typeof(Business3), typeof(IBusiness123), new List<Parameter>
                                                                                             {
                                                                                                 new Parameter {Name = "Business", Value = "${Business5}"},
                                                                                                 new Parameter {Name = "innerDao1", Value = "${Dao1}"},
                                                                                                 new Parameter {Name = "innerDao2", Value = "${Dao2}"}
                                                                                             });
            container.AddComponent("Business4", typeof(Business4), typeof(IBusiness45));
            container.AddComponent("Business5", typeof(Business5), typeof(IBusiness45),new List<Parameter>
                                                                                               {
                                                                                                   new Parameter {Name = "parameter1", Value = "parameter1"},
                                                                                                   new Parameter {Name = "parameter2", Value = "2"},
                                                                                               });
            container.AddComponent("Dao1", typeof(Dao1), typeof(IDao123));
            container.AddComponent("Dao2", typeof(Dao2), typeof(IDao123));
            container.AddComponent("Dao3", typeof(Dao3), typeof(IDao123));
            container.AddComponent("Dao4", typeof(Dao4), typeof(IDao45));
            container.AddComponent("Dao5", typeof(Dao5), typeof(IDao45));
        }

        #endregion

        public void ProcessResolve(IIocContainer container)
        {
            var result1 = container.Resolve<IBusiness123>();
            var result2 = container.Resolve<IBusiness123>("Business2");
            var result3 = container.Resolve<IBusiness123>("Business3");
            var result4 = container.Resolve<IBusiness45>();
            var result5 = container.Resolve<IBusiness45>("Business5");
        }
    }
}